/**
* jrMask v0.1
* 
* @author Pedro Junior <v.ju.ni.or.v@gmail.com>
* @example jrMask('.element', 'dinheiro');
*/

(function (W, $) {
    var 
    Mask = function (elem, mask) {
        return new Mask.fn.init(elem, mask);
    },

    Masks =
    {
        /**
        * Limpa Caracteres Não numericos e limita ao tamanho definido
        *
        * @param {string} valor Entrada
        * @param {integer} length Tamanho
        * @return {string}
        */
        _numeric: function (valor, length) {
            length = length || 100;
            return (valor + '')
                .replace(/\D/g, '')
                .replace(new RegExp('^(\\d{' + length + '}).*$'), '$1');
        },

        upper: function (valor) {
            return (valor + '').toUpperCase();
        },

        telefone: function (valor) {
            return Masks._numeric(valor, 10)
	            .replace(/^(\d{2})(\d+)/, '($1) $2') // DDD
	            .replace(/(\d{4})(\d+)$/, '$1-$2'); // Tel
        },

        dinheiro: function (valor) {
            return 'R$ ' + Masks._numeric(valor)
	            .replace(/^([0]+)/, '') // Limpa 0 (zeros) no começo
	            .replace(/^(\d)$/, '0,0$1') // Se for um digito coloca como centavo
	            .replace(/^(\d{2})$/, '0,$1') // Se for dois digitos também
	            .replace(/(\d+)(\d{2})$/, '$1,$2') // Qualquer número mais os centavos
	            .replace(/(\d{1,3})(\d{3,})/g, '$1.$2'); // Milhares
        },

        dinheiroReverse: function (valor) {
            return parseFloat(Masks._numeric(valor));
        },

        data: function (valor) {
            return Masks._numeric(valor, 10)
                .replace(/^(\d{2})(\d+)/, '$1/$2')
                .replace(/(\d{2})(\d+)/, '$1/$2');
        },

        cnpj: function (valor) {
            // 99.999.999/9999-99
            return Masks._numeric(valor, 14)
                .replace(/^(\d{14})(\d+)/, '$1') // Remove números adicionais
                .replace(/^(\d{2})(\d+)/, '$1.$2') // Formata os 2 primeiros digitos
                .replace(/(\d{3})(\d+)/, '$1.$2')
                .replace(/(\d{3})(\d+)/, '$1/$2')
                .replace(/(\d{4})(\d+)/, '$1-$2');
        },

        cpf: function (valor) {
            // 999.999.999-99
            return Masks._numeric(valor, 11)
                .replace(/^(\d{11})(\d+)/, '$1') // Remove números adicionais
                .replace(/^(\d{3})(\d+)/, '$1.$2')
                .replace(/(\d{3})(\d+)/g, '$1.$2')
                .replace(/(\d{3})(\d+)$/, '$1-$2');
        },

        cep: function (valor) {
            // 04236-230
            return Masks._numeric(valor, 8)
                .replace(/^(\d{8})(\d+)/, '$1') // Remove números adicionais
                .replace(/^(\d{5})(\d+)$/, '$1-$2');
        },

        numero: function (valor) {
            return Masks._numeric(valor);
        },

        hacker: function (valor) {
            var mapa = {
                'a': '4',
                'e': '3',
                'g': '9',
                'i': '1',
                'o': '0',
                'q': '6',
                's': '5',
                't': '7',
                'z': '2'
            };

            return valor.replace(/\w/ig, function (match) {
                var lower = match.toLowerCase();
                return mapa[lower] ? mapa[lower] : match;
            });
        }
    };

    Mask.fn = Mask.prototype = {
        init: function (elem, mask) {
            var 
            self = this,
	        $elem = $(elem),
	        parser = Masks[mask];

            if ('function' === typeof parser) {
                $elem.unbind('keyup').keyup(function () {
                    $elem.val(parser.apply(self.masks, [this.value]));
                })
	            .keyup();
            }
        },

        delegate: function (elem, mask) {
            var 
            parser = Masks[mask];

            $(W.document).delegate(elem, 'keyup', function () {
                this.value = parser.apply(Masks, [this.value]);
            });
        },

        autoload: function () {
            var self = this;

            self.delegate('input.dinheiro', 'dinheiro');
            self.delegate('input.telefone', 'telefone');
            self.delegate('input.numero', 'numero');
            self.delegate('input.data', 'data');
            self.delegate('input.cnpj', 'cnpj');
            self.delegate('input.cpf', 'cpf');
            self.delegate('input.cep', 'cep');
            self.delegate('input.upper, textarea.upper', 'upper');
        }
    };

    Mask.masks = Masks;
    Mask.fn.autoload();

    W.jrMask = Mask;
} (window, jQuery));